home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * As a special exception, the Free Software Foundation gives permission
- * for additional uses of the text contained in its release of GUILE.
- *
- * The exception is that, if you link the GUILE library with other files
- * to produce an executable, this does not by itself cause the
- * resulting executable to be covered by the GNU General Public License.
- * Your use of that executable is in no way restricted on account of
- * linking the GUILE library code into it.
- *
- * This exception does not however invalidate any other reasons why
- * the executable file might be covered by the GNU General Public License.
- *
- * This exception applies only to the code released by the
- * Free Software Foundation under the name GUILE. If you copy
- * code from other Free Software Foundation releases into a copy of
- * GUILE, as the General Public License permits, the exception does
- * not apply to the code that you add in this way. To avoid misleading
- * anyone as to the status of such modified files, you must delete
- * this exception notice from them.
- *
- * If you write modifications of your own for GUILE, it is your choice
- * whether to permit this exception to apply to your modifications.
- * If you do not wish that, delete this exception notice.
- */
-
-
- #include <stdio.h>
- #include "_scm.h"
-
-
-
- typedef struct
- {
- SCM rtd;
- SCM name;
- SCM fields;
- SCM printer;
- } rtd_type;
-
- typedef union
- {
- struct
- {
- SCM proc;
- SCM rtd;
- } pred;
- struct
- {
- SCM proc;
- SCM rtd;
- SCM index;
- } acc;
- struct
- {
- SCM proc;
- SCM rtd;
- SCM recsize;
- SCM indices;
- } constr;
- } rec_cclo;
-
- long scm_tc16_record;
-
- /* Record-type-descriptor for record-type-descriptors */
- static SCM the_rtd_rtd;
-
- /* Record <= [rtd, ... elts ... ] */
- #define REC_RTD(x) (VELTS(x)[0])
- #define RECP(x) (scm_tc16_record==TYP16(x))
- #define RTDP(x) (RECP(x) && the_rtd_rtd==REC_RTD(x))
- #define RTD_NAME(x) (((rtd_type *)CDR(x))->name)
- #define RTD_FIELDS(x) (((rtd_type *)CDR(x))->fields)
- #define RTD_PRINTER(x) (((rtd_type *)CDR(x))->printer)
- #define RCLO_RTD(x) (((rec_cclo *)CDR(x))->pred.rtd)
-
- #ifdef ARRAYS
- #define MAKE_REC_INDS(n) scm_make_uve((long)n, MAKINUM(1))
- #define REC_IND_REF(x, i) VELTS(x)[(i)]
- #define REC_IND_SET(x, i, val) VELTS(x)[(i)] = (val)
- #else
- #define MAKE_REC_INDS(n) scm_make_vector(MAKINUM(n), INUM0)
- #define REC_IND_REF(x, i) INUM(VELTS(x)[(i)])
- #define REC_IND_SET(x, i, val) VELTS(x)[(i)] = MAKINUM(val)
- #endif
-
- static char s_record[] = "record";
-
- PROC (s_record_p, "record?", 1, 0, 0, scm_record_p);
- #ifdef __STDC__
- SCM
- scm_record_p (SCM obj)
- #else
- SCM
- scm_record_p (obj)
- SCM obj;
- #endif
- {
- return (NIMP (obj) && RECP (obj) ? BOOL_T : BOOL_F);
- }
-
-
- PROC (s_record_predicate_procedure, " record-predicate-procedure", 2, 0, 0, scm_record_predicate_procedure);
- #ifdef __STDC__
- static SCM
- scm_record_predicate_procedure (SCM cclo, SCM obj)
- #else
- static SCM
- scm_record_predicate_procedure (cclo, obj)
- SCM cclo;
- SCM obj;
- #endif
- {
- if (NIMP (obj) && RECP (obj) && (REC_RTD (obj) == RCLO_RTD (cclo)))
- return BOOL_T;
- return BOOL_F;
- }
-
-
- static SCM f_record_predicate_procedure;
-
- PROC (s_record_predicate, "record-predicate", 1, 0, 0, scm_record_predicate);
- #ifdef __STDC__
- SCM
- scm_record_predicate (SCM rtd)
- #else
- SCM
- scm_record_predicate (rtd)
- SCM rtd;
- #endif
- {
- SCM cclo = scm_makcclo (f_record_predicate_procedure, 2L);
- ASSERT (NIMP (rtd) && RTDP (rtd), rtd, ARG1, s_record_predicate);
- RCLO_RTD (cclo) = rtd;
- return cclo;
- }
-
-
- PROC (s_record_type_descriptor, "record-type-descriptor", 1, 0, 0, scm_record_type_descriptor);
- #ifdef __STDC__
- SCM
- scm_record_type_descriptor (SCM rec)
- #else
- SCM
- scm_record_type_descriptor (rec)
- SCM rec;
- #endif
- {
- if (IMP (rec) || !RECP (rec))
- return BOOL_F;
- return REC_RTD (rec);
- }
-
- static SCM f_record_constructor_procedure;
-
- PROC (s_record_constructor, "record-constructor", 1, 1, 0, scm_record_constructor);
- #ifdef __STDC__
- SCM
- scm_record_constructor (SCM rtd, SCM flds)
- #else
- SCM
- scm_record_constructor (rtd, flds)
- SCM rtd;
- SCM flds;
- #endif
- {
- SCM flst, fld;
- SCM cclo = scm_makcclo (f_record_constructor_procedure, (long) sizeof (rec_cclo) / sizeof (SCM));
- rec_cclo *ptr = (rec_cclo *) CDR (cclo);
- sizet i, j;
- ASSERT (NIMP (rtd) && RTDP (rtd), rtd, ARG1, s_record_constructor);
- ptr->constr.rtd = rtd;
- i = scm_ilength (RTD_FIELDS (rtd));
- ptr->constr.recsize = MAKINUM (i);
- if (UNBNDP (flds))
- {
- ptr->constr.indices = MAKE_REC_INDS (i);
- while (i--)
- REC_IND_SET (ptr->constr.indices, i, i + 1);
- }
- else
- {
- ASSERT (NIMP (flds) && CONSP (flds), flds, ARG2, s_record_constructor);
- ptr->constr.indices = MAKE_REC_INDS (scm_ilength (flds));
- for (i = 0; NIMP (flds); i++, flds = CDR (flds))
- {
- fld = CAR (flds);
- ASSERT (NIMP (fld) && SYMBOLP (fld), fld, ARG2, s_record_constructor);
- flst = RTD_FIELDS (rtd);
- for (j = 0;; j++, flst = CDR (flst))
- {
- if (fld == CAR (flst))
- {
- REC_IND_SET (ptr->constr.indices, i, j + 1);
- break;
- }
- ASSERT (NNULLP (flst), fld, ARG2, s_record_constructor);
- }
- }
- }
- return cclo;
- }
-
- PROC (s_record_constructor_procedure, " record-constructor-procedure", 0, 0, 1, scm_record_constructor_procedure);
- #ifdef __STDC__
- static SCM
- scm_record_constructor_procedure (SCM args)
- #else
- static SCM
- scm_record_constructor_procedure (args)
- SCM args;
- #endif
- {
- SCM cclo = CAR (args);
- SCM rec, inds = (((rec_cclo *) CDR (cclo))->constr.indices);
- sizet i = INUM (((rec_cclo *) CDR (cclo))->constr.recsize);
- args = CDR (args);
- NEWCELL (rec);
- DEFER_INTS;
- SETCHARS (rec, scm_must_malloc ((i + 1L) * sizeof (SCM), s_record));
- SETNUMDIGS (rec, i + 1L, scm_tc16_record);
- ALLOW_INTS;
- while (i--)
- VELTS (rec)[i + 1] = UNSPECIFIED;
- REC_RTD (rec) = RCLO_RTD (cclo);
- for (i = 0; i < LENGTH (inds); i++, args = CDR (args))
- {
- ASSERT (NNULLP (args), SCM_UNDEFINED, WNA, s_record_constructor_procedure);
- VELTS (rec)[REC_IND_REF (inds, i)] = CAR (args);
- }
- ASSERT (NULLP (args), SCM_UNDEFINED, WNA, s_record_constructor_procedure);
- return rec;
-
- }
-
-
- /* Makes an accessor or modifier.
- A cclo with 2 env elts -- rtd and field-number. */
- #ifdef __STDC__
- static SCM
- makrecclo (SCM proc, SCM rtd, SCM field, char *what)
- #else
- static SCM
- makrecclo (proc, rtd, field, what)
- SCM proc;
- SCM rtd;
- SCM field;
- char *what;
- #endif
- {
- SCM flst;
- SCM cclo = scm_makcclo (proc, 3L);
- int i;
- ASSERT (RTDP (rtd), rtd, ARG1, what);
- ASSERT (NIMP (field) && SYMBOLP (field), field, ARG2, what);
- RCLO_RTD (cclo) = rtd;
- flst = RTD_FIELDS (rtd);
- for (i = 1;; i++)
- {
- ASSERT (NNULLP (flst), field, ARG2, what);
- if (CAR (flst) == field)
- break;
- flst = CDR (flst);
- }
- (((rec_cclo *) CDR (cclo))->acc.index) = MAKINUM (i);
- return cclo;
- }
-
-
- PROC (s_rec_accessor1, " rec-accessor1", 2, 0, 0, scm_rec_accessor1);
- #ifdef __STDC__
- static SCM
- scm_rec_accessor1 (SCM cclo, SCM rec)
- #else
- static SCM
- scm_rec_accessor1 (cclo, rec)
- SCM cclo;
- SCM rec;
- #endif
- {
- ASSERT (NIMP (rec) && RECP (rec), rec, ARG1, s_rec_accessor1);
- ASSERT (RCLO_RTD (cclo) == REC_RTD (rec), rec, ARG1, s_rec_accessor1);
- return VELTS (rec)[INUM (((rec_cclo *) CDR (cclo))->acc.index)];
- }
-
-
- PROC (s_rec_modifier1, " rec-modifier1", 3, 0, 0, scm_rec_modifier1);
- #ifdef __STDC__
- static SCM
- scm_rec_modifier1 (SCM cclo, SCM rec, SCM val)
- #else
- static SCM
- scm_rec_modifier1 (cclo, rec, val)
- SCM cclo;
- SCM rec;
- SCM val;
- #endif
- {
- ASSERT (NIMP (rec) && RECP (rec), rec, ARG1, s_rec_modifier1);
- ASSERT (RCLO_RTD (cclo) == REC_RTD (rec), rec, ARG1, s_rec_modifier1);
- VELTS (rec)[INUM (((rec_cclo *) CDR (cclo))->acc.index)] = val;
- return UNSPECIFIED;
- }
-
-
- static SCM f_rec_accessor1;
-
-
- PROC (s_record_accessor, "record-accessor", 2, 0, 0, scm_record_accessor);
- #ifdef __STDC__
- SCM
- scm_record_accessor (SCM rtd, SCM field)
- #else
- SCM
- scm_record_accessor (rtd, field)
- SCM rtd;
- SCM field;
- #endif
- {
- return makrecclo (f_rec_accessor1, rtd, field, s_record_accessor);
- }
-
-
- static SCM f_rec_modifier1;
-
- PROC (s_record_modifier, "record-modifier", 2, 0, 0, scm_record_modifier);
- #ifdef __STDC__
- SCM
- scm_record_modifier (SCM rtd, SCM field)
- #else
- SCM
- scm_record_modifier (rtd, field)
- SCM rtd;
- SCM field;
- #endif
- {
- return makrecclo (f_rec_modifier1, rtd, field, s_record_modifier);
- }
-
-
-
- SCM *scm_loc_makrtd;
-
- PROC (s_make_record_type, "make-record-type", 2, 0, 1, scm_make_record_type);
- #ifdef __STDC__
- SCM
- scm_make_record_type (SCM name, SCM fields, SCM args)
- #else
- SCM
- scm_make_record_type (name, fields, args)
- SCM name;
- SCM fields;
- SCM args;
- #endif
- {
- SCM n;
- SCM printer;
-
- #ifndef RECKLESS
- ASSERT(SYMBOLP(name), name, ARG1, s_make_record_type);
-
- if (scm_ilength (fields) < 0)
- errout:scm_wta (fields, (char *) ARG2, s_make_record_type);
- for (n = fields; NIMP (n); n = CDR (n))
- if (!SYMBOLP (CAR (n)))
- goto errout;
-
- if (NIMP(args) && CONSP(args)) {
- printer = CAR(args);
- args = CDR(args);
- } else
- printer = BOOL_F;
-
- #endif
- return scm_apply(*scm_loc_makrtd,
- name, scm_cons2 (fields, printer, listofnull));
- }
-
-
- #ifdef __STDC__
- static SCM
- markrec (SCM ptr)
- #else
- static SCM
- markrec (ptr)
- SCM ptr;
- #endif
- {
- sizet i;
- if GC8MARKP
- (ptr) return BOOL_F;
- SETGC8MARK (ptr);
- for (i = NUMDIGS (ptr); --i;)
- if NIMP
- (VELTS (ptr)[i]) scm_gc_mark (VELTS (ptr)[i]);
- return REC_RTD (ptr);
- }
-
-
- #ifdef __STDC__
- static sizet
- freerec (SCM ptr)
- #else
- static sizet
- freerec (ptr)
- SCM ptr;
- #endif
- {
- scm_must_free (CHARS (ptr));
- return sizeof (SCM) * NUMDIGS (ptr);
- }
-
-
- #ifdef __STDC__
- static int
- recprin1 (SCM exp, SCM port, int writing)
- #else
- static int
- recprin1 (exp, port, writing)
- SCM exp;
- SCM port;
- int writing;
- #endif
- {
- SCM rtd = REC_RTD(exp);
- SCM name = RTD_NAME(rtd);
- SCM pfunc = RTD_PRINTER(rtd);
-
- if (pfunc == BOOL_F) {
- sizet i;
- SCM names = RTD_FIELDS (rtd);
-
- scm_puts ("#s(", port);
- scm_iprin1 (name, port, 0);
-
- for (i = 1; i < NUMDIGS (exp); i++)
- {
- scm_putc (' ', port);
- scm_iprin1 (CAR (names), port, 0);
- names = CDR (names);
- scm_putc (' ', port);
- scm_iprin1 (VELTS (exp)[i], port, writing);
- }
- scm_putc (')', port);
- } else if (scm_procedurep(pfunc) != BOOL_F)
- scm_apply(pfunc,
- exp, scm_cons2(port, writing ? BOOL_T : BOOL_F, listofnull));
- else {
- scm_puts("#<", port);
- scm_iprin1(name, port, 0);
- scm_putc(' ', port);
- scm_intprint(exp, 16, port);
- scm_putc('>', port);
- }
-
- return 1;
- }
-
-
- #ifdef __STDC__
- static SCM
- scm_recequal (SCM rec0, SCM rec1)
- #else
- static SCM
- scm_recequal (rec0, rec1)
- SCM rec0;
- SCM rec1;
- #endif
- {
- sizet i = NUMDIGS (rec0);
- if (i != NUMDIGS (rec1))
- return BOOL_F;
- if (REC_RTD (rec0) != REC_RTD (rec1))
- return BOOL_F;
- while (--i)
- if (FALSEP (scm_equal (VELTS (rec0)[i], VELTS (rec1)[i])))
- return BOOL_F;
- return BOOL_T;
- }
-
- static scm_smobfuns recsmob = {markrec, freerec, recprin1, scm_recequal};
-
- static char s_name[] = "name";
- static char s_fields[] = "fields";
- static char s_printer[] = "printer";
-
- #ifdef __STDC__
- void
- scm_init_record (void)
- #else
- void
- scm_init_record ()
- #endif
- {
- SCM i_name = CAR (scm_intern (s_name, (sizeof s_name) - 1));
- SCM i_fields = CAR (scm_intern (s_fields, (sizeof s_fields) - 1));
- SCM i_printer = CAR (scm_intern (s_printer, (sizeof s_printer) - 1));
- scm_tc16_record = scm_newsmob (&recsmob);
-
- NEWCELL (the_rtd_rtd);
- SETCHARS (the_rtd_rtd, scm_must_malloc ((long) sizeof (rtd_type), s_record));
- SETNUMDIGS (the_rtd_rtd, (long) sizeof (rtd_type) / sizeof (SCM), scm_tc16_record);
-
- REC_RTD (the_rtd_rtd) = the_rtd_rtd;
- RTD_NAME (the_rtd_rtd) = scm_makfromstr (s_record, (sizeof s_record) - 1, 0);
- RTD_FIELDS (the_rtd_rtd) = scm_cons(i_name, scm_cons2(i_fields, i_printer, EOL));
- RTD_PRINTER (the_rtd_rtd) = BOOL_F;
-
- scm_sysintern ("record:rtd", the_rtd_rtd);
-
- #include "record.x"
-
- f_record_predicate_procedure = CDR (scm_intern0 (s_record_predicate_procedure));
- f_record_constructor_procedure = CDR (scm_intern0 (s_record_constructor_procedure));
- f_rec_accessor1 = CDR (scm_intern0 (s_rec_accessor1));
- f_rec_modifier1 = CDR (scm_intern0 (s_rec_modifier1));
- scm_sysintern ("record-type-descriptor?", scm_record_predicate (the_rtd_rtd));
- scm_sysintern ("record-type-name", scm_record_accessor (the_rtd_rtd, i_name));
- scm_sysintern ("record-type-field-names", scm_record_accessor (the_rtd_rtd, i_fields));
- scm_loc_makrtd = &CDR (scm_sysintern ("RTD:make", scm_record_constructor (the_rtd_rtd, SCM_UNDEFINED)));
- scm_add_feature (s_record);
- }
-
-